home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / aros / source / exec / memory / src / allocabs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  3.8 KB  |  155 lines

  1. /*
  2.     (C) 1995 AROS - The Amiga Replacement OS
  3.     $Id: allocabs.c 1.1 1995/11/14 22:31:07 digulla Exp digulla $
  4.     $Log: allocabs.c $
  5.  * Revision 1.1  1995/11/14  22:31:07  digulla
  6.  * Initial revision
  7.  *
  8.     Desc:
  9.     Lang: english
  10. */
  11. #include "exec_intern.h"
  12. #include "memory.h"
  13. #include <exec/memory.h>
  14. #include <exec/alerts.h>
  15.  
  16. /*****************************************************************************
  17.  
  18.     NAME */
  19.     #include <clib/exec_protos.h>
  20.  
  21.     __AROS_LH2(APTR, AllocAbs,
  22.  
  23. /*  SYNOPSIS */
  24.     __AROS_LA(unsigned long, byteSize, D0),
  25.     __AROS_LA(APTR         , location, A1),
  26.  
  27. /*  LOCATION */
  28.     struct ExecBase *, SysBase, 34, Exec)
  29.  
  30. /*  FUNCTION
  31.     Allocate some memory from the system memory pool at a given address.
  32.  
  33.     INPUTS
  34.     byteSize - Number of bytes you want to get
  35.     location - Where you want to get the memory
  36.  
  37.     RESULT
  38.     A pointer to some memory including the requested bytes or NULL if
  39.     the memory couldn't be allocated
  40.  
  41.     NOTES
  42.  
  43.     EXAMPLE
  44.  
  45.     BUGS
  46.  
  47.     SEE ALSO
  48.     FreeMem()
  49.  
  50.     INTERNALS
  51.  
  52.     HISTORY
  53.        17-10-95    created by M. Fleischer
  54.     26-10-95    digulla adjusted to new calling scheme
  55.  
  56. ******************************************************************************/
  57. {
  58.     __AROS_FUNC_INIT
  59.     struct MemChunk *p1,*p2,*p3,*p4;
  60.     struct MemHeader *mh;
  61.  
  62.     /* Zero bytes requested? May return everything ;-). */
  63.     if(!byteSize)
  64.     return NULL;
  65.  
  66.     /* Align size to the requirements */
  67.     byteSize+=(ULONG)location&(MEMCHUNK_TOTAL-1);
  68.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  69.  
  70.     /* Align the location as well */
  71.     location=(APTR)((ULONG)location&~(MEMCHUNK_TOTAL-1));
  72.  
  73.     /* Start and end(+1) of the block */
  74.     p3=(struct MemChunk *)location;
  75.     p4=(struct MemChunk *)((UBYTE *)p3+byteSize);
  76.  
  77.     /* Protect the memory list from access by other tasks. */
  78.     Forbid();
  79.  
  80.     /* Loop over MemHeader structures */
  81.     mh=(struct MemHeader *)SysBase->MemList.lh_Head;
  82.     while(mh->mh_Node.ln_Succ)
  83.     {
  84.     /* Test if the memory belongs to this MemHeader. */
  85.     if(mh->mh_Lower<=location&&mh->mh_Upper>location)
  86.     {
  87.         /*
  88.         The free memory list is only single linked, i.e. to remove
  89.         elements from the list I need the node's predessor. For the
  90.         first element I can use freeList->mh_First instead of a real
  91.         predessor.
  92.         */
  93.         p1=(struct MemChunk *)&mh->mh_First;
  94.         p2=p1->mc_Next;
  95.  
  96.         /* Follow the list to find a chunk with our memory. */
  97.         while(p2!=NULL)
  98.         {
  99. #if !defined(NO_CONSISTENCY_CHECKS)
  100.         /*
  101.             Do some constistency checks:
  102.             1. All MemChunks must be aligned to
  103.                MEMCHUNK_TOTAL.
  104.             2. The end (+1) of the current MemChunk
  105.                must be lower than the start of the next one.
  106.         */
  107.         if(  ((ULONG)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  108.             ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  109.             &&p2->mc_Next!=NULL))
  110.             Alert(AN_MemCorrupt|AT_DeadEnd);
  111. #endif
  112.         /* Found a chunk that fits? */
  113.         if((UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p4&&p2<=p3)
  114.         {
  115.             /* Check if there's memory left at the end. */
  116.             if((UBYTE *)p2+p2->mc_Bytes!=(UBYTE *)p4)
  117.             {
  118.             /* Yes. Add it to the list */
  119.             p4->mc_Next=p2->mc_Next;
  120.             p4->mc_Bytes=(UBYTE *)p2+p2->mc_Bytes-(UBYTE *)p4;
  121.             p2->mc_Next=p4;
  122.             }
  123.  
  124.             /* Check if there's memory left at the start. */
  125.             if(p2!=p3)
  126.             /* Yes. Adjust the size */
  127.             p2->mc_Bytes=(UBYTE *)p3-(UBYTE *)p2;
  128.             else
  129.             /* No. Skip the old chunk */
  130.             p1->mc_Next=p2->mc_Next;
  131.  
  132.             /* Adjust free memory count */
  133.             mh->mh_Free-=byteSize;
  134.  
  135.             /* Return the memory */
  136.             Permit();
  137.             return p3;
  138.         }
  139.         /* goto next chunk */
  140.         p1=p2;
  141.         p2=p2->mc_Next;
  142.         }
  143.         /* The MemHeader didn't have the memory */
  144.         break;
  145.     }
  146.     /* Test next MemHeader */
  147.     mh=(struct MemHeader *)mh->mh_Node.ln_Succ;
  148.     }
  149.     /* There's nothing we could do */
  150.     Permit();
  151.     return NULL;
  152.     __AROS_FUNC_EXIT
  153. } /* AllocAbs */
  154.  
  155.